package com.lxh.cptp.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Pair;
import cn.hutool.json.JSONUtil;
import com.lxh.cptp.config.WxCpTpConfiguration;
import com.lxh.cptp.constant.ChangeTypeEnum;
import com.lxh.cptp.constant.InfoTypeEnum;
import com.lxh.cptp.constant.WxCpTpInnerConstant;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.cp.api.WxCpTpService;
import me.chanjar.weixin.cp.bean.WxCpTpCorp;
import me.chanjar.weixin.cp.bean.WxCpTpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpTpXmlPackage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.util.crypto.WxCpTpCryptUtil;
import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.json.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * created by lanxinghua@2dfire.com on 2020/2/14
 * 企业微信第三方应用开发
 */
@RestController
public class WxCpTpController extends BaseController{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private String SUIT_ID = "ww141f5c1b0bfe0bc2";
    private WxCpTpService tpService;

    /**
     * 数据回调url，应用中发送消息接收
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @RequestMapping("/callback/data")
    public String data(@RequestParam(name = "msg_signature", required = false) String signature,
                       @RequestParam(name = "timestamp", required = false) String timestamp,
                       @RequestParam(name = "nonce", required = false) String nonce,
                       @RequestParam(name = "echostr", required = false) String echostr,
                       HttpServletRequest request) {
        logger.info("数据回调");
        logger.info("signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", signature, timestamp, nonce, echostr);
        tpService = WxCpTpConfiguration.getCpTpService(SUIT_ID);
        if (StringUtils.isEmpty(echostr)){
            try {
                BufferedReader reader = request.getReader();
                StringBuffer buffer = new StringBuffer();
                String line = " ";
                while (null != (line = reader.readLine())) {
                    buffer.append(line);
                }
                String postData = buffer.toString();
                String decryptMsgs = new WxCpTpCryptUtil(tpService.getWxCpTpConfigStorage()).decrypt(signature, timestamp, nonce, postData);
                System.out.println("数据回调-解密后的xml数据:" + decryptMsgs);
                WxCpTpXmlPackage tpXmlPackage = WxCpTpXmlPackage.fromXml(decryptMsgs);
                System.out.println(JSONUtil.toJsonStr(tpXmlPackage));

                // 消息回复
                WxCpXmlOutMessage outMessage = this.route(SUIT_ID, tpXmlPackage);
                String plainXml = XStreamTransformer.toXml((Class) outMessage.getClass(), outMessage);
                logger.info("\n组装回复信息：{}", plainXml);

                WxCpTpCryptUtil pc = new WxCpTpCryptUtil(tpService.getWxCpTpConfigStorage());
                return pc.encrypt(plainXml);
            }catch (Exception e){
                logger.error("校验失败：" + e.getMessage());
                return "success";
            }
        }
        try {
            if (tpService.checkSignature(signature, timestamp, nonce, echostr)) {
                return new WxCpTpCryptUtil(tpService.getWxCpTpConfigStorage()).decrypt(echostr);
            }
        } catch (Exception e) {
            logger.error("校验签名失败：" + e.getMessage());
        }
        return "success";
    }

    private WxCpXmlOutMessage route(String suitId, WxCpTpXmlPackage message) {
        // 日志处理
        WxCpTpConfiguration.getHandler("log").handle(message, null);
        // 消息处理
        return WxCpTpConfiguration.getHandler("msg").handle(message, null);
    }


    /**
     * 指令回调url  通讯录，部门变更，  授权变更，  ticket数据
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/suite/receive")
    public String suite(@RequestParam("msg_signature") String signature,
                        @RequestParam("timestamp") String timestamp,
                        @RequestParam("nonce") String nonce,
                        @RequestParam(value = "echostr", required = false) String echostr,
                        HttpServletRequest request,
                        HttpServletResponse response) throws Exception {
        logger.info("指令回调URL-调用我了");
        logger.info("signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]", signature, timestamp, nonce, echostr);

        tpService = WxCpTpConfiguration.getCpTpService(SUIT_ID);

        // 不为空为回调配置请求
        if (null != echostr) {
            try {
                if (tpService.checkSignature(signature, timestamp, nonce, echostr)) {
                    String decrypt = new WxCpTpCryptUtil(tpService.getWxCpTpConfigStorage()).decrypt(echostr);
                    logger.info("指令回调URL结果：" + decrypt);
                    return decrypt;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        BufferedReader reader = request.getReader();
        StringBuffer buffer = new StringBuffer();
        String line = " ";
        while (null != (line = reader.readLine())) {
            buffer.append(line);
        }
        String postData = buffer.toString();
        String decryptMsgs = null;
        try {
            decryptMsgs = new WxCpTpCryptUtil(tpService.getWxCpTpConfigStorage()).decrypt(signature, timestamp, nonce, postData);
            System.out.println("解密后的xml数据:" + decryptMsgs);
        }catch (Exception e){
            logger.error("校验失败：" + e.getMessage());
            return "success";
        }
        WxCpTpXmlMessage wxCpTpXmlMessage = WxCpTpXmlMessage.fromXml(decryptMsgs);
        InfoTypeEnum infoTypeEnum = InfoTypeEnum.getByInstance(wxCpTpXmlMessage.getInfoType());
        if (infoTypeEnum == null){
            throw new Exception("不支持该类型操作");
        }
        Map<String, Object> jsonObject = wxCpTpXmlMessage.getAllFieldsMap();
        switch (infoTypeEnum) {
            //（每十分钟）推送ticket。ticket会实时变更，并用于后续接口的调用。
            case SUITE_TICKET: {
                String suitId = wxCpTpXmlMessage.getSuiteId();
                String suiteTicket = wxCpTpXmlMessage.getSuiteTicket();
                Integer timeStamp = Convert.toInt(wxCpTpXmlMessage.getTimeStamp());
                logger.info("推送ticket成功:" + jsonObject.toString());
                WxCpTpConfigStorage tpConfig = tpService.getWxCpTpConfigStorage();
                tpConfig.updateSuiteTicket(suiteTicket, 20*60);
                logger.info("suit ticket缓存更新成功");

                String suitAccessToken = tpService.getSuiteAccessToken();
                logger.info("suitAccessToken:" + suitAccessToken);
                break;
            }
            // 企业微信应用市场发起授权时，企业微信后台会推送授权成功通知
            case CREATE_AUTH:{
                logger.info("创建授权：" + jsonObject.toString());
                String suiteId = wxCpTpXmlMessage.getSuiteId();
                String authCode = wxCpTpXmlMessage.getAuthCode();
                String timeStamp = wxCpTpXmlMessage.getTimeStamp();
                WxCpTpCorp permanentCode = tpService.getPermanentCode(authCode);
                logger.info("永久授权码：" + permanentCode);
                break;
            }
            case CHANGE_AUTH:{
                logger.info("变更授权");
                // TODO: 2020/2/14
                break;
            }
            case CHANGE_CONTACT:{
                logger.info("通讯录变更");
                String changeType = jsonObject.get(WxCpTpInnerConstant.CHANGE_TYPE).toString();
                ChangeTypeEnum changeTypeEnum = ChangeTypeEnum.getByInstance(changeType);
                if (Objects.isNull(changeTypeEnum)){
                    throw new Exception("该类型通讯录变更不存在");
                }
                switch (changeTypeEnum){
                    case DELETE_USER:{
                        logger.info("删除用户");
                        break;
                    }
                    case UPDATE_TAG:{
                        logger.info("更新标签");
                        break;
                    }
                    case DELETE_PARTY:{
                        logger.info("删除部门");
                        break;
                    }
                    default:{
                        break;
                    }
                }
                break;
            }
            case CHANGE_EXTERNAL_CONTACT:{
                logger.info("外部联系人");
                String changeType = jsonObject.get(WxCpTpInnerConstant.CHANGE_TYPE).toString();
                ChangeTypeEnum changeTypeEnum = ChangeTypeEnum.getByInstance(changeType);
                if (Objects.isNull(changeTypeEnum)){
                    throw new Exception("该类型CHANGE_EXTERNAL_CONTACT不存在");
                }
                switch (changeTypeEnum){
                    case ADD_EXTERNAL_CONTACT:{
                        logger.info("添加客户" + jsonObject.toString());
                        String externalUserID = jsonObject.get("ExternalUserID").toString();
                        String welcomeCode = jsonObject.get("WelcomeCode").toString();
                        if (StringUtils.isEmpty(welcomeCode)){
                            logger.warn("welcomeCode没获取到，用户可能已经设置了欢迎语！！！");
                            break;
                        }
                        String userID = jsonObject.get("UserID").toString();
                        String suiteId = jsonObject.get("SuiteId").toString();
                        String authCorpId = jsonObject.get("AuthCorpId").toString();
                        System.out.println("欢迎code：" + welcomeCode);
                        sendWelcome(tpService, welcomeCode);
                        break;
                    }
                    default:{
                        break;
                    }
                }
            }
            default: {
                break;
            }
        }
        return "success";
    }



    /**
     * 发送欢迎语
     * @param tpService
     * @param welcome_code
     * @throws Exception
     */
    public void sendWelcome(WxCpTpService tpService, String welcome_code) throws Exception{
        String auth_corpId = "ww4007bc86bede5885";
        String permCode = authMap.get(auth_corpId);
        WxAccessToken wxAccessToken = tpService.getCorpToken(auth_corpId, permCode);
        logger.info("获取企业凭证：" + JSONUtil.toJsonStr(wxAccessToken));

        String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=%s";
        // image、link和miniprogram只能有一个
        String postData_back = "{\n" +
                "    \"welcome_code\":\""+welcome_code+"\",\n" +
                "    \"text\": {\n" +
                "        \"content\":\"欢迎，自定义文本消息内容\"\n" +
                "    },\n" +
                "    \"image\": {\n" +
                "        \"media_id\": \"1Qio5JosY6ylJN9LzyOSrhCYkZQA0IzDYV-PSOXca4bWaX1B-uzTRBXXS1H3bPcg2\"\n" +
                "    },\n" +
                "    \"link\": {\n" +
                "        \"title\": \"消息标题\",\n" +
                "        \"picurl\": \"https://assets.2dfire.com/frontend/277ec5572aad73d80b3bcaa5b57fc65b.png\",\n" +
                "        \"desc\": \"消息描述\",\n" +
                "        \"url\": \"http://2dfire.com\"\n" +
                "    },\n" +
                "    \"miniprogram\": {\n" +
                "        \"title\": \"消息标题找店\",\n" +
                "        \"pic_media_id\": \"1Qio5JosY6ylJN9LzyOSrhCYkZQA0IzDYV-PSOXca4bWaX1B-uzTRBXXS1H3bPcg2\",\n" +
                "        \"appid\": \"wx3c2dd923cc336aea\",\n" +
                "        \"page\": \"/pages/findShop\"\n" +
                "    }\n" +
                "}\n";

        String postData = "{\n" +
                "    \"welcome_code\":\""+welcome_code+"\",\n" +
                "    \"text\": {\n" +
                "        \"content\":\"欢迎，自定义文本消息内容\"\n" +
                "    },\n" +
                "    \"miniprogram\": {\n" +
                "        \"title\": \"消息标题找店\",\n" +
                "        \"pic_media_id\": \"1xWyPP9Pcf2owxOso6fBCTsELmjTyehO-aOOOWZs54NNCQLfNCrW8PXsoYIp1jaTX\",\n" +
                "        \"appid\": \"wx3c2dd923cc336aea\",\n" +
                "        \"page\": \"/pages/findShop\"\n" +
                "    }\n" +
                "}\n";
        String result = tpService.post(String.format(url, wxAccessToken.getAccessToken()), postData);
        //JsonObject jsonObject = new JsonParser().parse(result).getAsJsonObject();
        System.out.println("发送欢迎语："+ result);
    }

}
